setlastbank macro
        mov edi,esi
        shr edi,13
        mov eax,[memmap+edi*4]
        mov [lastbank],eax
endm

encodePC macro                                  ;translate esi from 6502 PC to DS offset
        setlastbank
        add esi,eax
endm

save6502 macro                                  ;save 6502 regs
        mov [_Z_A],edx
        mov [_X_Y],ecx
        mov [_S],ebx
        sub esi,[lastbank]
        mov [_PC],esi
endm

restore6502 macro                               ;restore 6502 regs
        mov esi,[_PC]
        mov ebx,[_S]
        mov edx,[_Z_A]
        mov ecx,[_X_Y]
        add esi,[lastbank]
endm

encodeP macro extra     ;put all flags into AL (blech)
        and [Cflag],C
        and [Nflag],N
        cmp [Vflag],0
        setnz ah
        cmp dh,0
        setz al
        shl ah,6        ;V
        add al,al       ;Z
        or ah,[Cflag]   ;C
        or al,[DIflag]  ;DI
        or ah,extra     ;(R+B)
        or al,[Nflag]   ;N
        or al,ah
endm

decodeP macro                   ;unpack 6502 flags from DH
        local ep0
        mov [Nflag],dh
        mov [DIflag],dh
        mov [Cflag],dh          ;C
        mov [Vflag],dh
        and [DIflag],D+I        ;D,I
        and [Vflag],V           ;V
        and dh,Z
        xor dh,Z                ;Z
endm

;----------------------------------------------------------------------------

fetch   macro count
        sub [cycles],count
        jmp op_fetch
        align 4
endm

fetch1  macro
        js timeout
        test [int_flags],-1
        jnz interrupt
        fetch2
endm

fetch2  macro                                   ;execute next instruction
        if DEBUG
                mov [lastaddr],esi
        endif
        mov edi,[esi]
        and edi,0ffh
        inc esi
        jmp [op_table+edi*4]
endm

;----------------------------------------------------------------------------
readmem macro
        mov ebp,edi
        shr ebp,13
        call [read_tbl+ebp*4]
        ;EAX=value, EDI,EBP=?
endm

writemem macro
        mov ebp,edi
        shr ebp,13
        call [write_tbl+ebp*4]
        ;EAX,EDI,EBP=?
endm

;----------------------------------------------------------------------------

_IMM    equ     1                       ;immediate
_ZP     equ     2                       ;zero page
_ABS    equ     3                       ;absolute

;----------------------------------------------------------------------------

push16  macro
        mov [ebx],ah
        dec bl
        mov [ebx],al
        dec bl
endm

push8   macro x
        mov [ebx],x
        dec bl
endm

pop16   macro
        xor eax,eax
        inc bl
        mov al,[ebx]
        inc bl
        mov ah,[ebx]
endm

pop8    macro x
        inc bl
        mov x,[ebx]
endm

;----------------------------------------------------------------------------

doABS   macro                           ;absolute               $xxxx
_type   =       _ABS 
        movzx edi,word ptr [esi]
        add esi,2
endm

doAIX   macro                           ;absolute indexed X     $xxxx,X
_type   =       _ABS 
        movzx edi,ch
        add di,[esi]
        add esi,2
endm


doAIX2  macro                           ;absolute indexed X     $xxxx,X
_type   =       _ABS                    ;(add cycle for page crossing)
        movzx eax,ch
        add ax,[esi]
        add esi,2
        mov edi,eax
        sub al,ch
        sbb eax,eax
        and eax,3
        sub [cycles],eax
endm

doAIY   macro                           ;absolute indexed Y     $xxxx,Y
_type   =       _ABS
        movzx edi,cl
        add di,[esi]
        add esi,2
endm

doAIY2  macro                           ;absolute indexed Y     $xxxx,Y
_type   =       _ABS                    ;(add one cycle for page crossing)
        movzx eax,cl
        add ax,[esi]
        add esi,2
        mov edi,eax
        sub al,cl
        sbb eax,eax
        and eax,3
        sub [cycles],eax
endm

doIMM   macro                           ;immediate              #$xx
_type   =       _IMM
endm

doIIX   macro                           ;indexed indirect X     ($xx,X)
_type   =       _ABS 
        xor eax,eax
        xor edi,edi
        mov al,[esi]
        add al,ch
        mov di,fs:[eax]
        inc esi
endm

doIIY   macro                           ;indirect indexed Y     ($xx),Y
_type   =       _ABS
        xor eax,eax
        xor edi,edi
        mov al,[esi]
        mov di,fs:[eax]
        mov al,cl
        add di,ax
        inc esi
endm

doIIY2   macro                          ;indirect indexed Y     ($xx),Y
_type   =       _ABS                    ;(add cycle for page crossing)
        movzx edi,byte ptr [esi]
        xor eax,eax
        mov al,cl
        add ax,fs:[edi]
        inc esi
        mov edi,eax
        sub al,cl
        sbb eax,eax
        and eax,3
        sub [cycles],eax
endm

doZ     macro                           ;zero page              $xx
_type   =       _ZP
        movzx edi,byte ptr [esi]
        inc esi
endm

doZIX   macro                           ;zero page indexed X    $xx,X
_type   =       _ZP
        xor eax,eax
        mov al,[esi]
        add al,ch
        mov edi,eax
        inc esi
endm

doZIY   macro                           ;zero page indexed Y    $xx,Y
_type   =       _ZP
        mov edi,[esi]
        add edi,ecx
        and edi,0ffh
        inc esi
endm

;----------------------------------------------------------------------------

opADC   macro
        if _type eq _ABS
                readmem
                shr [Cflag],1
                adc dl,al
                mov dh,dl       ;Z
                mov [Nflag],dl  ;N
                rcl [Cflag],1   ;C
                seto [Vflag]    ;V
        elseif _type eq _ZP
                shr [Cflag],1
                adc dl,fs:[edi]
                mov dh,dl       ;Z
                mov [Nflag],dl  ;N
                rcl [Cflag],1   ;C
                seto [Vflag]    ;V
        else
                shr [Cflag],1
                adc dl,[esi]
                mov dh,dl       ;Z
                mov [Nflag],dl  ;N
                rcl [Cflag],1   ;C
                seto [Vflag]    ;V
                inc esi
        endif
endm

opAND   macro
        if _type eq _ABS
                readmem
                and dl,al
                mov dh,dl       ;Z
                mov [Nflag],dl  ;N
        elseif _type eq _ZP
                and dl,fs:[edi]
                mov dh,dl       ;Z
                mov [Nflag],dl  ;N
        else
                and dl,[esi]
                mov dh,dl       ;Z
                mov [Nflag],dl  ;N
                inc esi
        endif
endm

opASL   macro
        if _type eq _ABS
                push edi
                readmem
                pop edi
                shl al,1
                mov dh,dl       ;Z
                mov [Nflag],dl  ;N
                rcl [Cflag],1   ;C
                writemem
        else
                shl byte ptr fs:[edi],1
                mov dh,fs:[edi] ;Z
                rcl [Cflag],1   ;C
                mov [Nflag],dh
        endif
endm

opBIT   macro
        if _type eq _ABS
                readmem
        else
                mov al,fs:[edi]
        endif
        mov [Nflag],al  ;N
        mov dh,al
        and al,V
        and dh,dl       ;Z
        mov [Vflag],al  ;V
endm

opCMP   macro
        if _type eq _ABS
                mov dh,dl
                readmem
                sub dh,al       ;Z
                cmc
                rcl [Cflag],1   ;C
                mov [Nflag],dh  ;N
        elseif _type eq _ZP
                mov dh,dl
                sub dh,fs:[edi] ;Z
                cmc
                rcl [Cflag],1   ;C
                mov [Nflag],dh  ;N
        else
                mov dh,dl
                sub dh,[esi]    ;Z
                cmc
                rcl [Cflag],1   ;C
                mov [Nflag],dh  ;N
                inc esi
        endif
endm

opCPX   macro
        if _type eq _ABS
                mov dh,ch
                readmem
                sub dh,al       ;Z
                cmc
                rcl [Cflag],1   ;C
                mov [Nflag],dh  ;N
        elseif _type eq _ZP
                mov dh,ch
                sub dh,fs:[edi] ;Z
                cmc
                rcl [Cflag],1   ;C
                mov [Nflag],dh  ;N
        else
                mov dh,ch
                sub dh,[esi]    ;Z
                cmc
                rcl [Cflag],1   ;C
                mov [Nflag],dh  ;N
                inc esi
        endif
endm

opCPY   macro
        if _type eq _ABS
                mov dh,cl
                readmem
                sub dh,al       ;Z
                cmc
                rcl [Cflag],1   ;C
                mov [Nflag],dh  ;N
        elseif _type eq _ZP
                mov dh,cl
                sub dh,fs:[edi] ;Z
                cmc
                rcl [Cflag],1   ;C
                mov [Nflag],dh  ;N
        else
                mov dh,cl
                sub dh,[esi]    ;Z
                cmc
                rcl [Cflag],1   ;C
                mov [Nflag],dh  ;N
                inc esi
        endif
endm

opDEC   macro
        if _type eq _ABS
                push edi
                readmem
                pop edi
                dec al
                mov dh,al       ;Z
                mov [Nflag],al  ;N
                writemem
        else
                dec byte ptr fs:[edi]
                mov dh,fs:[edi] ;Z
                mov [Nflag],dh  ;N
        endif
endm

opEOR   macro
        if _type eq _ABS
                readmem
                xor dl,al
                mov dh,dl       ;Z
                mov [Nflag],dl  ;N
        elseif _type eq _ZP
                xor dl,fs:[edi]
                mov dh,dl       ;Z
                mov [Nflag],dl  ;N
        else
                xor dl,[esi]
                inc esi
                mov dh,dl       ;Z
                mov [Nflag],dl  ;N
        endif
endm

opINC   macro
        if _type eq _ABS
                push edi
                readmem
                pop edi
                inc al
                mov dh,al       ;Z
                mov [Nflag],al  ;N
                writemem
        else
                inc byte ptr fs:[edi]
                mov dh,fs:[edi] ;Z
                mov [Nflag],dh  ;N
        endif
endm

opLDA   macro
        if _type eq _ABS
                readmem
                mov dl,al
                mov dh,al       ;Z
                mov [Nflag],al  ;N
        elseif _type eq _ZP
                mov dl,fs:[edi]
                mov dh,fs:[edi] ;Z
                mov [Nflag],dl  ;N
        else
                mov dl,[esi]
                inc esi
                mov dh,dl       ;Z
                mov [Nflag],dl  ;N
        endif
endm

opLDX   macro
        if _type eq _ABS
                readmem
                mov ch,al
                mov dh,al       ;Z
                mov [Nflag],al  ;N
        elseif _type eq _ZP
                mov ch,fs:[edi]
                mov dh,fs:[edi] ;Z
                mov [Nflag],ch  ;N
        else
                mov ch,[esi]
                inc esi
                mov dh,ch       ;Z
                mov [Nflag],ch  ;N
        endif
endm

opLDY   macro
        if _type eq _ABS
                readmem
                mov cl,al
                mov dh,al       ;Z
                mov [Nflag],al  ;N
        elseif _type eq _ZP
                mov cl,fs:[edi]
                mov dh,fs:[edi] ;Z
                mov [Nflag],cl  ;N
        else
                mov cl,[esi]
                inc esi
                mov dh,cl       ;Z
                mov [Nflag],cl  ;N
        endif
endm

opLSR   macro
        if _type eq _ABS
                push edi
                readmem
                pop edi
                mov [Cflag],al  ;C
                shr al,1
                mov dh,al       ;Z
                mov [Nflag],al  ;N
                writemem
        else
                shr byte ptr fs:[edi],1
                mov dh,fs:[edi] ;Z
                rcl [Cflag],1   ;C
                mov [Nflag],dh  ;N
        endif
endm

opORA   macro
        if _type eq _ABS
                readmem
                or dl,al
                mov dh,dl       ;Z
                mov [Nflag],dl  ;N
        elseif _type eq _ZP
                or dl,fs:[edi]
                mov dh,dl       ;Z
                mov [Nflag],dl  ;N
        else
                or dl,[esi]
                inc esi
                mov dh,dl       ;Z
                mov [Nflag],dl  ;N
        endif
endm

opROL   macro
        if _type eq _ABS
                push edi
                readmem
                pop edi
                shr [Cflag],1
                rcl al,1
                rcl [Cflag],1   ;C
                mov dh,al       ;Z
                mov [Nflag],al  ;N
                writemem
        else
                mov al,fs:[edi]
                shr [Cflag],1
                rcl al,1
                rcl [Cflag],1   ;C
                mov dh,al       ;Z
                mov [Nflag],al  ;N
                mov fs:[edi],al
        endif
endm

opROR   macro
        if _type eq _ABS
                push edi
                readmem
                pop edi
                shr [Cflag],1
                mov [Cflag],al  ;C
                rcr al,1
                mov dh,al       ;Z
                mov [Nflag],al  ;N
                writemem
        else
                mov dh,fs:[edi]
                shr [Cflag],1
                mov [Cflag],dh  ;C
                rcr dh,1        ;Z
                mov [Nflag],dh  ;N
                mov fs:[edi],dh
        endif
endm

opSBC   macro
        if _type eq _ABS
                readmem
                shr [Cflag],1
                cmc
                sbb dl,al
                cmc
                mov dh,dl       ;Z
                mov [Nflag],dl  ;N
                rcl [Cflag],1   ;C
                seto [Vflag]    ;V
        elseif _type eq _ZP
                shr [Cflag],1
                cmc
                sbb dl,fs:[edi]
                cmc
                mov dh,dl       ;Z
                mov [Nflag],dl  ;N
                rcl [Cflag],1   ;C
                seto [Vflag]    ;V
        else
                shr [Cflag],1
                cmc
                sbb dl,[esi]
                cmc
                mov dh,dl       ;Z
                mov [Nflag],dl  ;N
                rcl [Cflag],1   ;C
                seto [Vflag]    ;V
                inc esi
        endif
endm

opSTA   macro
        if _type eq _ABS
                mov al,dl
                writemem
        else
                mov fs:[edi],dl
        endif
endm

opSTX   macro
        if _type eq _ABS
                mov al,ch
                writemem
        else
                mov fs:[edi],ch
        endif
endm

opSTY   macro
        if _type eq _ABS
                mov al,cl
                writemem
        else
                mov fs:[edi],cl
        endif
endm
